/*
 * Classe StatSeven
 *                          - Obtem os dados da estatística 7 da base de dados (SQLite3 + ADO.NET) 
 * 							- Guarda esses dados numa Lista (C# Collections)
 * 							- Ordena os dados
 * 							- Escreve os resultados na consola e no ficheiro de texto respectivo
 *							- Tem como atributo o estabelecimento para o qual será calculada a estatística
 *
 *@Author: Fábio Miguel Vitória Carreto - 5618 - Engenharia Informática - Diurno
 *@Version: 03/07/2011
 * 
 * 
 * */


using System;
using System.Collections.Generic;
using System.Data;
using Mono.Data.SqliteClient;
using System.IO;

public class StatSeven
{
	public string estabelecimento;

	
	public StatSeven (string estabelecimento)
	{
		this.estabelecimento = estabelecimento;
		
		List<StructFinalStatSete> statSeven = this.getData();
		List<StructFinalStatSete> statOrdenada = this.mostraStatOrdenada(statSeven);
		this.showResultsConsole(statOrdenada);
		this.showResultsFile(statOrdenada);	
	}
	
	//Ordena os dados por ordem crescente da contagem na lista
	public List<StructFinalStatSete> mostraStatOrdenada(List<StructFinalStatSete> stat)
	{
		stat.Sort(delegate(StructFinalStatSete s1, StructFinalStatSete s2) 
		          { return s1.count.CompareTo(s2.count); });
		
		return stat;
	}
	
	//Mostra resultados na consola
	public void showResultsConsole(List<StructFinalStatSete> stat)
	{
		
		Console.WriteLine("Número de Docentes que subiram de Categoria\nEstabelecimento: " + this.estabelecimento);
		Console.WriteLine("\nResultados (Ordenados por contagem crescente): \n");
		stat.ForEach(delegate(StructFinalStatSete s) 
		{ 
			Console.WriteLine(String.Format("Ano: 200{0}, Número: {1}", s.ano, s.count)); 
		});
		
	}
	
	//Mostra resultados no ficheiro respectivo
	public void showResultsFile(List<StructFinalStatSete> stat)
	{
		
		string file = "Estatísticas/statSeven.txt";
	
		TextWriter tw = new StreamWriter(file);
		tw.WriteLine(DateTime.Now);
		tw.WriteLine("Sistema Operativo: " + Environment.OSVersion.ToString());
		tw.WriteLine("");
		tw.WriteLine("Estatística 7 - Número de Docentes que subiram de categoria\nEstabelecimento: " + this.estabelecimento +
			" em cada ano.");
		tw.WriteLine(Environment.NewLine + "(Resultados ordenados por ordem crescente da contagem)");
		tw.Close();
			

		
		stat.ForEach(delegate(StructFinalStatSete s) 
		{
			File.AppendAllText(file, String.Format("Ano = 200{0}, Número = {1}" + 
			                                       Environment.NewLine, s.ano, s.count));
		});
		
		
		Console.WriteLine("\nOs resultados da estatística 7 foram também guardados em ficheiro de texto.");
		Console.WriteLine("Localização: " + file);
		
	}
	
	//Obtém os dados da estatística e retorna-os numa lista de objectos destinados para tal
	public List<StructFinalStatSete> getData()
	{
		List<StructFinalStatSete> stat = new List<StructFinalStatSete>();
		
		for(int ano = 0 ; ano < 10 ; ano++)
		{
			string connectionString = "URI=file:rebides.db,version=3";
			IDbConnection dbcon;
			dbcon = (IDbConnection) new SqliteConnection(connectionString);
			dbcon.Open();
			IDbCommand dbcmd = dbcon.CreateCommand();
			
			if(ano == 0)
			{
				//Quando o ano é 2000, não há dados anteriores para comparar
				//e fazer então a estatística
				stat.Add(new StructFinalStatSete(ano, 0));
			}
			else
			{
				
				//Verifica primeiro qual os códigos de estabelecimento no ano anterior
				//e actual (ano do ciclo)
				int cod_estabAnt = this.findEstab(ano - 1, this.estabelecimento, dbcon);
				int cod_estabAct = this.findEstab(ano, this.estabelecimento, dbcon);
				
				//Obtem uma lista com os docentes do ano anterior e outra com os do ano actual 
				//(para o estabelecimento pretendido)
				List<StructStatSeven> docAnt = this.findDoc(ano - 1, cod_estabAnt, dbcon);
				List<StructStatSeven> docAct = this.findDoc(ano, cod_estabAct, dbcon);
				
				//Variável que irá conter a contagem final da estatística
				int counter = 0;
				
				//Percorre a lista com os docentes do ano anterior
				foreach(StructStatSeven docPrev in docAnt)
				{
					
					//Verifica se no ano actual existe o mesmo docente (objecto) que existia no ano anterior
					StructStatSeven teste = docAct.Find((delegate(StructStatSeven o) { return o.docente == docPrev.docente; }));
					
					//Caso exista compara-se a categoria dos dois (que são a mesma pessoa)
					if(teste != null)
					{
						//Caso a categoria seja a mesma, quer dizer que ele nao subiu
						if(teste.categoria.Equals(docPrev.categoria))
						{
							continue;
							
						}
						else
						{
							//Quando a categoria mudou então este docente entra na contagem
							counter++;
						}
					}
					else
					{
						continue;
					}	
			
				}
				
				//Guarda os resultados numa lista de objectos StructFinalStatSete
				stat.Add(new StructFinalStatSete(ano, counter));
			
			}
			
			
			
		}
	
		return stat;
		
	}
	
	//Método que irá obter o codigo de estabelecimento pelo seu nome e ano
	public int findEstab(int ano, string estabelecimento, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;

		string sqlEstab = String.Format("SELECT DISTINCT id FROM estabelecimento WHERE " + 
				                           "ano = {0} AND designacao LIKE '{1}'", ano, estabelecimento);
			 
		dbcmd.CommandText = sqlEstab;
		reader = dbcmd.ExecuteReader();
				
		string estabelecimento_id = null;
				
		while(reader.Read()) 
		{
			estabelecimento_id = reader.GetString (0);
		}
		
		return int.Parse(estabelecimento_id);
		
	}
	
	//Método que devolve a lista de docentes e respectiva categoria
	//num determinado ano para um dado estabelecimento
	public List<StructStatSeven> findDoc(int ano, int cod_estab, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;
		
		List<StructStatSeven> docentes = new List<StructStatSeven>();
		
		string sqlFinal = String.Format("SELECT docente_id, categoria_id FROM registodocencia WHERE " +
					"ano = {0} AND estabelecimento_id = {1}", ano, cod_estab);
				
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
				
		while(reader.Read()) 
		{
			string docente = reader.GetString (0);
			string categoria = reader.GetString (1);
			docentes.Add(new StructStatSeven(ano, docente, categoria));
		}
		
		return docentes;
		
	}
	
	
}

//Objecto que servirá controlo à estatística
//Tem como atributos docente o ano e categoria e servirá para 
//criar as listas de docentes
//que posteriormente serão comparadas pelo docente e 
//pela categoria de cada um em anos consecutivos
public class StructStatSeven
{
	
	public int ano;
	public string docente;
	public string categoria;
	
	public StructStatSeven(int ano, string docente, string categoria)
	{
		this.ano = ano;
		this.docente = docente;
		this.categoria = categoria;
		
	}
}

//Objecto que servirá de base à estatística
//Tem como atributos o ano e a contagem final
public class StructFinalStatSete
{
	public int ano;
	public int count;
	
	public StructFinalStatSete(int ano, int count)
	{
		this.ano = ano;
		this.count = count;
	}
}


